home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-05-24 | 7.1 KB | 264 lines | [TEXT/CWIE] |
- //
- // This code sample demonstrates several ways to unmount a volume.
- //
- // [1] Call MoreFiles and have it take its best shot.
- //
- // [2] Augment MoreFiles with a little Finder-style interface
- // and some strategic trash-emptying.
- //
- // [3] Send an AppleEvent to Finder and have it do the whole thing.
- //
- // A real strategy might use all of the above. Basically, the problem is
- // this: although UnmountVol has been patched so that some commonly open
- // files (mostly having to do with desktop info) are closed before the
- // volume unmounts, not all are, and in particular files associated
- // with the trash on shared volumes are not automagically closed.
- //
- // Each of the three above-mentioned methods has its flaws.
- //
- // [1] It wouldn't be in the spirit of MoreFiles to empty
- // the trash silently when attempting to unmount, so it's
- // not surprising MoreFiles doesn't do it.
- //
- // [2] Getting confirmation from the user involves posting an
- // alert, which is not always easy for non-apps.
- //
- // [3] Requires the unmounter to send AppleEvents, which is
- // not always easy for non-apps, and may require user to
- // switch to Finder to confirm alerts, which also is not
- // always easy for non-apps.
- //
- // Your program may have to combine methods to achieve the effect it
- // needs. And your program should be ready for the methods to fail --
- // not that you should expect a proper implementation to fail, but
- // your program shouldn't assume that it will not.
- //
- // Of course, if some application other than Finder or At Ease has files
- // open on the volume, the volume simply will not unmount, and that's a
- // legitimate error condition.
- //
- // Note this sample in its current state will unmount all AppleShare
- // volumes. The interesting function is PutAwayOneVolume, and it has
- // nothing to do with AppleShare in particular. The rest of the functions
- // are here simply to drive PutAwayOneVolume.
- //
- // You may incorporate this sample code into your applications without
- // restriction, though the sample code has been provided "AS IS" and the
- // responsibility for its operation is 100% yours. However, what you are
- // not permitted to do is to redistribute the source as "DTS Sample Code"
- // after having made changes. If you're going to re-distribute the source,
- // we require that you make it clear in the source that the code was
- // descended from Apple Sample Code, but that you've made changes.
- //
- // Complaints and kudos to:
- //
- // Pete Gontier
- // Apple Macintosh Developer Technical Support
- // <gurgle@apple.com>
- //
- // Change history:
- //
- // PG 03/20/96 St. Luther points out that 'hpbp->volumeParam.ioVFSID'
- // is not a sufficient test for AppleShare; check the driver
- // name instead; this makes the sample a little more accurate
- // but a little less useful, since nobody specifies volumes
- // by driver name. However, the portion of this code which
- // cares about which volumes to unmount is only here to make
- // the sample run anyway; users will have to adapt this code
- // regardless; PutAwayOneVolume is the interesting code, and
- // it's not affected by this change.
- //
- // PG 03/20/96 PutAwayVolumes doesn't really need to know the names of the
- // volumes it's indexing. Save some stack.
- //
- // PG 03/21/96 Use MoreFiles version of UnmountAndEject. Keeping my own
- // copy was just stupid, especially since I plan to use more
- // of MoreFiles.
- //
- // PG 03/21/96 After conversation with Jim, realized the AppleEvent
- // strategy is not always best. This version makes use of
- // semi-documented 'ReleaseFolder' call to deal with shared
- // trash folders.
- //
-
- #define OLDROUTINELOCATIONS 0
- #define OLDROUTINENAMES 0
- #define SystemSevenOrLater 1
-
- #ifndef __FILES__
- # include <Files.h>
- #endif
-
- #ifndef __LOWMEM__
- # include <LowMem.h>
- #endif
-
- #ifndef __DEVICES__
- # include <Devices.h>
- #endif
-
- #ifndef __PLSTRINGFUNCS__
- # include <PLStringFuncs.h>
- #endif
-
- #ifndef __PROCESSES__
- # include <Processes.h>
- #endif
-
- #include "PutAwayOneVolume.h"
-
- #define USE_INTERNAL_CODE 1
-
- //
- // USE_INTERNAL_CODE controls whether we send the AppleEvent to Finder
- // or use the internal code to unmount the volume ('ReleaseFolder').
- //
-
- enum
- {
- kCreatorCode_Finder = 'MACS',
- kCreatorCode_AtEase = 'mfdr'
- };
-
- static pascal OSErr GetCreatorOfFinderLikeProcess (OSType *processSignature)
- {
- OSErr err = noErr;
-
- #if !USE_INTERNAL_CODE
-
- ProcessSerialNumber psn = { kNoProcess, kNoProcess };
- ProcessInfoRec pir = { sizeof (pir), nil };
-
- #endif
-
- *processSignature = 0;
-
- #if !USE_INTERNAL_CODE
-
- pir.processAppSpec = nil;
-
- for (;;)
- {
- err = GetNextProcess (&psn);
- if (err)
- {
- if (err == procNotFound) err = noErr;
- break;
- }
-
- err = GetProcessInformation (&psn,&pir);
- if (err) break;
-
- if (pir.processSignature == kCreatorCode_Finder || pir.processSignature == kCreatorCode_AtEase)
- {
- *processSignature = pir.processSignature;
- break;
- }
- }
-
- #endif
-
- return err;
- }
-
- static pascal Boolean VolDriverNameIs (short vRefNum, ConstStr255Param potentialDriverName)
- {
- Boolean result = false;
-
- const VCB *vcbQueueScanner = (const VCB *) GetVCBQHdr ( )->qHead;
-
- while (vcbQueueScanner)
- {
- if (vcbQueueScanner->vcbVRefNum == vRefNum)
- {
- short csParam [11];
-
- if (!Status (vcbQueueScanner->vcbDRefNum,1,csParam))
- {
- DCtlHandle dCtlHandle = *(DCtlHandle *) csParam;
- DRVRHeaderPtr drvrHeaderPtr = (DRVRHeaderPtr) (**dCtlHandle).dCtlDriver;
- Boolean isHandle = (**dCtlHandle).dCtlFlags & dRAMBasedMask;
- ConstStr255Param drvrName = drvrHeaderPtr->drvrName;
- SInt8 hState;
-
- //
- // We lock the driver handle temporarily in case
- // <PLStringFuncs.glue.lib> (which contains
- // the implementation of PLstrcmp) lives in
- // another (potentially unloaded) code segment.
- //
-
- if (isHandle)
- {
- hState = HGetState ((Handle) drvrHeaderPtr);
- HLock ((Handle) drvrHeaderPtr);
- drvrName = (**(DRVRHeaderHandle)drvrHeaderPtr).drvrName;
- }
-
- result = !PLstrcmp (potentialDriverName,drvrName);
-
- if (isHandle)
- HSetState ((Handle) drvrHeaderPtr, hState);
- }
- }
-
- vcbQueueScanner = (const VCB *) (vcbQueueScanner->qLink);
- }
-
- return result;
- }
-
- static pascal OSErr PutAwayVolumes (const unsigned char *driverName)
- {
- OSErr err = noErr;
-
- OSType finderLikeProcess;
-
- if (!(err = GetCreatorOfFinderLikeProcess (&finderLikeProcess)))
- {
- HParmBlkPtr hpbp = (HParmBlkPtr) NewPtrClear (sizeof (*hpbp));
- if (!(err = MemError ( )))
- {
- hpbp->volumeParam.ioVolIndex = 1;
-
- for (;;)
- {
- err = PBHGetVInfoSync (hpbp);
- if (err)
- {
- if (err == nsvErr) err = noErr;
- break;
- }
-
- if (VolDriverNameIs (hpbp->volumeParam.ioVRefNum, driverName))
- {
- err = PutAwayOneVolume (hpbp->volumeParam.ioVRefNum, finderLikeProcess);
- if (err) break;
- }
-
- hpbp->volumeParam.ioVolIndex += 1;
- }
-
- DisposePtr ((Ptr) hpbp);
- if (!err) err = MemError ( );
- }
- }
-
- return err;
- }
-
- void main (void)
- {
- MaxApplZone ( );
- InitGraf (&(qd.thePort));
- InitFonts ( );
- InitWindows ( );
- InitMenus ( );
- TEInit ( );
- InitDialogs (nil);
-
- // (void) PutAwayVolumes ("\p.Sony");
-
- (void) PutAwayVolumes ("\p.AFPTranslator");
- }
-